package com.hapzxb.consumer.irule;

import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 从所有可用的provider中排除掉指定端口的provider，剩余provider进行随机选择
 */
public class ConstomRule implements IRule {

    private ILoadBalancer ld;

    /**
     *  要排除的提供者端口号集合
     */
    private List<Integer> excludPorts;

    public ConstomRule() {
    }

    public ConstomRule(List<Integer> excludPorts) {
        this.excludPorts = excludPorts;
    }

    @Override
    public Server choose(Object key) {
        // 获取所有可用的提供者
        List<Server> servers = ld.getReachableServers();

        // 获取所有排除了知道端口号的提供者
        List<Server> availableServers = this.getAvailableServers(servers);

        // 从剩余的提供者种随机获取可用的提供者
        return this.getAvailableRandomsSevers(availableServers);

    }

    /**
     * 获取所有排除了知道端口号的提供者
     *
     * @param servers
     * @return
     */
    private List<Server> getAvailableServers(List<Server> servers) {
        // 若不存在要排除的Server ,则直接将所有可用的Server返回
        if (excludPorts == null || excludPorts.size() == 0) {
            return servers;
        }

        // 定义一个集合，用于存放排除了知道端口号的server
        List<Server> aservers = new ArrayList<>();
        for (Server server : servers) {
            boolean flag = true;
            for (Integer port : excludPorts){
                if (server.getPort() == port) {
                    flag = false;
                    break;
                }
            }
            // 若flag 为false，说明上面的for循环执行了break，说明当前遍历的Server是排除掉的Server
            if (flag) {
                aservers.add(server);
            }
        }
        return aservers;
    }

    /**
     * 从剩余的提供者种随机获取可用的提供者
     *
     * @param availableServers
     * @return
     */
    private Server getAvailableRandomsSevers(List<Server> availableServers) {
        // 获取一个[0,availableServers.size()]的随机数
        int index = new Random().nextInt(availableServers.size());
        return availableServers.get(index);
    }



    @Override
    public void setLoadBalancer(ILoadBalancer iLoadBalancer) {
        this.ld = iLoadBalancer;
    }

    @Override
    public ILoadBalancer getLoadBalancer() {
        return ld;
    }
}
